`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:19:03 04/20/2011 
// Design Name: 
// Module Name:    Execution 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Execution(PCin, ALUSrc1, ALUSrc2, RS, RT, signExt, ALUOp, ALUresult, zero, sign, branchAddr,
						mtIn, ForA, ForB, MEMALUresult, WBwriteData, RegWriteIn, writeDstIn, MemtoRegIn, BranchIn, MemReadIn, MemWriteIn,
						mtOut, writeDstOut, RegWriteOut, MemtoRegOut, BranchOut, MemReadOut, MemWriteOut);


	input [15:0] PCin;
	input ALUSrc1;
	input ALUSrc2;
	input [15:0] RS;
	input [15:0] RT;
	input [15:0] MEMALUresult;
	input [15:0] WBwriteData;
	input [15:0] signExt;
	input [3:0] ALUOp;
	input [1:0] ForA, ForB;
	output [15:0] ALUresult;
	output zero;
	output sign;
	output [15:0] branchAddr;
	
	//Just passing through
	input [15:0] mtIn;
	input [3:0] writeDstIn;
	input RegWriteIn, MemtoRegIn, BranchIn, MemReadIn, MemWriteIn;
	
	output [15:0] mtOut;
	output [3:0] writeDstOut;
	output RegWriteOut, MemtoRegOut, BranchOut, MemReadOut, MemWriteOut;
	
	//Buffers added to safeguard against hold violations
	delay_buffer_1bit i_buf1(.a(RegWriteIn), .y(RegWriteOut));
	delay_buffer_1bit i_buf2(.a(MemtoRegIn), .y(MemtoRegOut));
	delay_buffer_1bit i_buf3(.a(BranchIn), .y(BranchOut));
	delay_buffer_1bit i_buf4(.a(MemReadIn), .y(MemReadOut));
	delay_buffer_1bit i_buf5(.a(MemWriteIn), .y(MemWriteOut));
	delay_buffer_4bit i_buf6(.a(writeDstIn), .y(writeDstOut));
	delay_buffer_16bit i_buf7(.a(mtIn), .y(mtOut));
	
	wire [15:0] ForwardMuxA;
	wire [15:0] ForwardMuxB;
	wire [15:0] ALUin1;
	wire [15:0] ALUin2;
	
	Mux_4to1_16bits i_Mux_FA(
		.a(RS), 
		.b(WBwriteData), 
		.c(MEMALUresult), 
		.d(4'b0000), 
		.sel(ForA), 
		.out(ForwardMuxA));
		
	Mux_4to1_16bits i_Mux_FB(
		.a(RT), 
		.b(WBwriteData), 
		.c(MEMALUresult), 
		.d(4'b0000), 
		.sel(ForB), 
		.out(ForwardMuxB));
	
	Mux_2to1_16bits i_Mux1(
		.a(ForwardMuxA), 
		.b(16'h0000), 
		.sel(ALUSrc1), 
		.out(ALUin1));

	Mux_2to1_16bits i_Mux2(
		.a(ForwardMuxB), 
		.b(signExt), 
		.sel(ALUSrc2), 
		.out(ALUin2));

	ALU i_ALU(
		.a(ALUin1), 
		.b(ALUin2), 
		.ALUOp(ALUOp), 
		.ALUresult(ALUresult), 
		.zero(zero), 
		.sign(sign));
	
	Adder_16bit i_Adder(
		.a(PCin), 
		.b(signExt), 
		.result(branchAddr));

endmodule
